package com.unproy.model.domain;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.Lob;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;


@Entity
@Table(name = "TBARTC")
public class Article implements Serializable, Comparable<Article>, Publishable {
	private static final long	serialVersionUID	= -1123454982456255170L;
	private Long				articleId;
	private Category			category;
	private SubCategory			subCategory;
	private User				createdBy;
	private Date				createdOn			= new Date();
	private Boolean				approved			= false;
	private User				approvedBy;
	private Date				approvedOn;
	private User				publishedBy;
	private Date				publishedOn;
	private String				title;
	private String				subTitle;
	private String				text;
	private Integer				hitCounter			= 0;
	private Date				lastUpdateDate		= new Date();
	private ArticleUpdate		lastArticleUpdate	= null;
	private List<ArticleUpdate>	articleUpdates		= new ArrayList<ArticleUpdate>();
	private Set<Tag>			tags				= new HashSet<Tag>();
	private List<Article>		relatedArticles		= new ArrayList<Article>();
	private Set<Media>			media				= new HashSet<Media>();
	private Set<MediaType>		library				= new HashSet<MediaType>();
	private List<Comment>		comments			= new ArrayList<Comment>();
	
	@Id
	@SequenceGenerator(name = "articleId", sequenceName = "SQARTC")
	@GeneratedValue(generator = "articleId", strategy = GenerationType.SEQUENCE)
	@Column(name = "ARTCID", unique = true, nullable = false)
	public Long getArticleId() {
		return this.articleId;
	}
	
	public void setArticleId(Long articleId) {
		this.articleId = articleId;
	}
	
	@ManyToOne(fetch = FetchType.EAGER)
	@JoinColumn(name = "CTGRID", nullable = false)
	public Category getCategory() {
		return this.category;
	}
	
	public void setCategory(Category categoryId) {
		this.category = categoryId;
	}
	
	@ManyToOne(fetch = FetchType.EAGER)
	@JoinColumn(name = "SCTGID")
	public SubCategory getSubCategory() {
		return this.subCategory;
	}
	
	public void setSubCategory(SubCategory subCategoryId) {
		this.subCategory = subCategoryId;
	}
	
	@ManyToOne(fetch = FetchType.EAGER)
	@JoinColumn(name = "CUSRID", nullable = false)
	@Override
	public User getCreatedBy() {
		return this.createdBy;
	}
	
	@Override
	public void setCreatedBy(User createdBy) {
		this.createdBy = createdBy;
	}
	
	@Column(name = "CRTDON", nullable = false)
	@Override
	public Date getCreatedOn() {
		return this.createdOn;
	}
	
	@Override
	public void setCreatedOn(Date createdOn) {
		this.createdOn = createdOn;
	}
	
	@Column(name = "ISAPRV", nullable = false)
	@Override
	public Boolean isApproved() {
		return this.approved;
	}
	
	@Override
	public void setApproved(Boolean approved) {
		this.approved = approved;
	}
	
	@ManyToOne(fetch = FetchType.LAZY)
	@JoinColumn(name = "AUSRID")
	@Override
	public User getApprovedBy() {
		return this.approvedBy;
	}
	
	@Override
	public void setApprovedBy(User approvedBy) {
		this.approvedBy = approvedBy;
	}
	
	@Column(name = "APRVON")
	@Override
	public Date getApprovedOn() {
		return this.approvedOn;
	}
	
	@Override
	public void setApprovedOn(Date approvedOn) {
		this.approvedOn = approvedOn;
	}
	
	@ManyToOne(fetch = FetchType.LAZY)
	@JoinColumn(name = "PUSRID")
	@Override
	public User getPublishedBy() {
		return this.publishedBy;
	}
	
	@Override
	public void setPublishedBy(User publisedBy) {
		this.publishedBy = publisedBy;
	}
	
	@Column(name = "PBSHON")
	@Override
	public Date getPublishedOn() {
		return this.publishedOn;
	}
	
	@Override
	public void setPublishedOn(Date publishedOn) {
		this.publishedOn = publishedOn;
	}
	
	@Column(name = "ATITLE", nullable = false)
	public String getTitle() {
		return this.title;
	}
	
	public void setTitle(String title) {
		this.title = title;
	}
	
	@Column(name = "SUBTIT")
	public String getSubTitle() {
		return this.subTitle;
	}
	
	public void setSubTitle(String subTitle) {
		this.subTitle = subTitle;
	}
	
	@Lob
	@Column(name = "ARTTXT", nullable = false)
	public String getText() {
		return this.text;
	}
	
	public void setText(String text) {
		this.text = text;
	}
	
	@Column(name = "HITCNT", nullable = false)
	public Integer getHitCounter() {
		return this.hitCounter;
	}
	
	public void setHitCounter(Integer hitCounter) {
		this.hitCounter = hitCounter;
	}
	
	@Column(name = "LUDATE", nullable = false)
	public Date getLastUpdateDate() {
		return this.lastUpdateDate;
	}
	
	public void setLastUpdateDate(Date lastUpdate) {
		this.lastUpdateDate = lastUpdate;
	}
	
	@OneToOne(fetch = FetchType.EAGER)
	@JoinColumn(name = "LAUPID")
	public ArticleUpdate getLastArticleUpdate() {
		return this.lastArticleUpdate;
	}
	
	public void setLastArticleUpdate(ArticleUpdate lastArticleUpdate) {
		this.lastArticleUpdate = lastArticleUpdate;
	}
	
	@OneToMany(fetch = FetchType.LAZY, mappedBy = "article")
	public List<ArticleUpdate> getArticleUpdates() {
		return this.articleUpdates;
	}
	
	public void setArticleUpdates(List<ArticleUpdate> articleUpdates) {
		this.articleUpdates = articleUpdates;
	}
	
	@ManyToMany(fetch = FetchType.EAGER)
	@JoinTable(name = "TBARTG", joinColumns = @JoinColumn(name = "ARTCID", nullable = false), inverseJoinColumns = @JoinColumn(name = "TAGSID", nullable = false))
	public Set<Tag> getTags() {
		return this.tags;
	}
	
	public void setTags(Set<Tag> tags) {
		this.tags = tags;
	}
	
	@OneToMany(fetch = FetchType.LAZY)
	@JoinTable(name = "TBRLAR", joinColumns = @JoinColumn(name = "ARCTID", nullable = false), inverseJoinColumns = @JoinColumn(name = "RARTID", nullable = false))
	public List<Article> getRelatedArticles() {
		return this.relatedArticles;
	}
	
	public void setRelatedArticles(List<Article> relatedArticles) {
		this.relatedArticles = relatedArticles;
	}
	
	@ManyToMany(fetch = FetchType.EAGER)
	@JoinTable(name = "TBARMD", joinColumns = @JoinColumn(name = "ARTCID", nullable = false), inverseJoinColumns = @JoinColumn(name = "MEDIID", nullable = false))
	public Set<Media> getMedia() {
		return this.media;
	}
	
	public void setMedia(Set<Media> media) {
		this.media = media;
	}
	
	@ManyToMany(fetch = FetchType.EAGER)
	@JoinTable(name = "TBARMT", joinColumns = @JoinColumn(name = "ARTCID", nullable = false), inverseJoinColumns = @JoinColumn(name = "MTYPID", nullable = false))
	public Set<MediaType> getLibrary() {
		return this.library;
	}
	
	public void setLibrary(Set<MediaType> library) {
		this.library = library;
	}
	
	@OneToMany(fetch = FetchType.LAZY, mappedBy = "article")
	public List<Comment> getComments() {
		return this.comments;
	}
	
	public void setComments(List<Comment> comments) {
		this.comments = comments;
	}
	
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((this.articleId == null) ? 0 : this.articleId.hashCode());
		result = prime * result + ((this.createdBy == null) ? 0 : this.createdBy.hashCode());
		result = prime * result + ((this.createdOn == null) ? 0 : this.createdOn.hashCode());
		return result;
	}
	
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Article other = (Article) obj;
		if (this.articleId == null) {
			if (other.articleId != null)
				return false;
		} else if (!this.articleId.equals(other.articleId))
			return false;
		if (this.createdBy == null) {
			if (other.createdBy != null)
				return false;
		} else if (!this.createdBy.equals(other.createdBy))
			return false;
		if (this.createdOn == null) {
			if (other.createdOn != null)
				return false;
		} else if (!this.createdOn.equals(other.createdOn))
			return false;
		return true;
	}
	
	@Override
	public int compareTo(Article article) {
		return getCreatedOn().compareTo(article.getCreatedOn());
	}
	
	@Override
	public String toString() {
		return getTitle();
	}
	
}
